﻿using System;
using System.Collections.Generic;
using System.Text;

namespace AppMain
{
    /// <summary>
    /// 思路：
    /// 同样的场景在服务器上可能存在多个,比如A和B玩家都在打副本1001
    /// 那么服务器的场景需要有一个UID
    /// 什么时候创建场景？
    /// 玩家登录游戏 或者 做进入场景的行为
    /// 玩家登录：检查玩家当前所在的场景id和uid,如果uid查找不到场景实例，则说明场景已经被删除了,玩家踢回到主城
    /// 玩家在主城：请求进入副本1001，创建1001场景并且生成uid，副本结束,销毁场景,踢出玩家
    /// 玩家在副本中,断线可以重连到副本
    /// sql上玩家得存一个普通场景的id与位置
    /// 还得存玩家在副本中的id与位置
    /// </summary>
    public class SceneMgr : Singleton<SceneMgr>
    {
        private Dictionary<long, BaseScene> map = new Dictionary<long, BaseScene>();

        protected override void initialize()
        {

        }

        public void tick(float frameTime)
        {
            var ier = map.GetEnumerator();
            while (ier.MoveNext())
            {
                ier.Current.Value.tick(frameTime);
            }
        }

        private T createScene<T>(long sceneId, long uid) where T : BaseScene, new()
        {
            T t = new T();
            t.uid = uid;
            t.sceneId = sceneId;
            t.initialize();
            map.Add(uid, t);
            return t;
        }

        public T getScene<T>(long uid) where T : BaseScene, new()
        {
            T t = default(T);
            BaseScene scene;
            if (map.TryGetValue(uid, out scene))
            {
                t = scene as T;
            }
            return t;
        }

        /// <summary>
        /// 是否有
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public bool hasScene(long uid)
        {
            return map.ContainsKey(uid);
        }

        public void roleEnterWorld(BaseRole role)
        {
            long copyUID = role.AttrMap.getAttr<long>(RoleAttr.CopySceneUID).Value;
            long sceneId = role.AttrMap.getAttr<long>(RoleAttr.SceneId).Value;
            sceneId = copyUID > 0 ? copyUID : sceneId;
            //踢到主城
            if (hasScene(sceneId))
            {
                BaseScene baseScene = getScene<BaseScene>(sceneId);
                baseScene.addRole(role);
            }
            else
            {
                BaseScene baseScene = createScene<BaseScene>(sceneId, sceneId);
                baseScene.addRole(role);
            }

        }

        public void roleEnterCopy(long sceneId, BaseRole role)
        {
            BaseScene baseScene = createScene<BaseScene>(sceneId, MathUtils.UniqueID);
            baseScene.addRole(role);
            role.AttrMap.changeAttr(RoleAttr.CopySceneId, baseScene.sceneId);
            role.AttrMap.changeAttr(RoleAttr.CopySceneUID, baseScene.uid);
        }

        public void removeRole(IRole role)
        {
            long copyUID = role.AttrMap.getAttr<long>(RoleAttr.CopySceneUID).Value;
            long sceneId = role.AttrMap.getAttr<long>(RoleAttr.SceneId).Value;
            sceneId = copyUID > 0 ? copyUID : sceneId;
            if (sceneId > 0)
            {
                BaseScene scene = this.getScene<BaseScene>(sceneId);
                if (scene != null)
                {
                    scene.removeRole(role);
                }
            }
        }
    }
}
